package com.xbongbong.saas.model.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.pojo.dto.ChangeRuleStatusDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.dao.PublicGroupSeniorDao;
import com.xbongbong.saas.domain.entity.PublicGroupSeniorEntity;
import com.xbongbong.saas.enums.SeniorFixedGroupEnum;
import com.xbongbong.saas.enums.SeniorPublicGroupTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.PublicGroupSeniorModel;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.sys.util.UserUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author lrj
 * @date 2022/4/14 9:38
 */
@Service("publicGroupSeniorModel")
public class PublicGroupSeniorModelImpl implements PublicGroupSeniorModel {

    @Resource
    private PublicGroupSeniorDao publicGroupSeniorDao;

    private static final Logger LOG = LoggerFactory.getLogger(PublicGroupSeniorModelImpl.class);
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private UserModel userModel;

    @Override
    public Integer insert(PublicGroupSeniorEntity entity) throws XbbException {
        long now = DateUtil.getInt();
        entity.setAddTime(now);
        entity.setUpdateTime(now);
        entity.setDel(BasicConstant.ZERO);
        return publicGroupSeniorDao.insert(entity);
    }

    @Override
    public void insertBatch(List<PublicGroupSeniorEntity> publicGroupSeniorEntityList) {
        publicGroupSeniorEntityList.forEach(item -> {
            long now = DateUtil.getInt();
            item.setAddTime(now);
            item.setUpdateTime(now);
            item.setDel(BasicConstant.ZERO);
        });
        publicGroupSeniorDao.insertBatch(publicGroupSeniorEntityList);
    }

    @Override
    public Integer save(PublicGroupSeniorEntity entity) throws XbbException {
        if(entity.getId() == null || entity.getId().equals(0L)) {
            return insert(entity);
        }
        return update(entity);
    }



    @Override
    public Integer deleteByKey(Long key, String corpid) {
        return publicGroupSeniorDao.deleteByKey(key, corpid);
    }

    @Override
    public PublicGroupSeniorEntity getByKey(Long key, String corpid) {
        return publicGroupSeniorDao.getByKey(key, corpid);
    }

    @Override
    public Integer updateBatch(List<PublicGroupSeniorEntity> list, String corpid) {
        return publicGroupSeniorDao.updateBatch(list, corpid);
    }

    @Override
    public Integer update(PublicGroupSeniorEntity publicGroup) {
        publicGroup.setUpdateTime((long)DateUtil.getInt());
        return publicGroupSeniorDao.update(publicGroup);
    }


    @Override
    public List<PublicGroupSeniorEntity> getByFormId(Long formId, String corpid,Integer del) {
        return publicGroupSeniorDao.getByFormId(formId, corpid,del);
    }

    @Override
    public Integer getEntitysCount(Map<String, Object> param) {
        return publicGroupSeniorDao.getEntitysCount(param);
    }

    @Override
    public Integer maxLevel(Long formId, String corpid) {
        return publicGroupSeniorDao.maxLevel(formId, corpid);
    }

    @Override
    public List<PublicGroupSeniorEntity> getByGroupName(String name, Long formId, String corpid,Integer status) {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid",corpid);
        param.put("del",BasicConstant.ZERO);
        param.put("formId",formId);
        param.put("name",name);
        param.put("status",status);
        return findEntitys(param);
    }

    @Override
    public List<PublicGroupSeniorEntity> findEntitys(Map<String, Object> param) {
        return publicGroupSeniorDao.findEntitys(param);
    }

    @Override
    public List<PublicGroupSeniorEntity> findEntityByStatus(String corpid,Long formId,Integer status) {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid",corpid);
        param.put("del",BasicConstant.ZERO);
        param.put("formId",formId);
        param.put("status",status);
        param.put("orderByStr","sort asc");
        return findEntitys(param);
    }

    @Override
    public List findEntitysWithoutSub(Map<String, Object> param) {
        return null;
    }



    @Override
    public JSONArray getGroupTree(String corpid, Long formId,Integer status) {
        JSONArray groupTree = new JSONArray();
        //获取启用状态的公海分组
        List<PublicGroupSeniorEntity> allGroupList = findEntityByStatus(corpid,formId,status);
        if (CollectionsUtil.isNotEmpty(allGroupList)){
            //处理无公海分组的排序，放到第一个
            for (int i = 0;i < allGroupList.size(); i++){
                PublicGroupSeniorEntity entity = allGroupList.get(i);
                if (Objects.equals(entity.getGroupType(),SeniorPublicGroupTypeEnum.NO_PUBLIC_GROUP.getType())){
                    Collections.swap(allGroupList,i,0);
                    break;
                }
            }
            for (PublicGroupSeniorEntity entity : allGroupList){
                if (Objects.equals(entity.getParentId(), BasicConstant.ZERO_LONG)){
                    JSONObject jsonObject = formatGroupJSONObject(allGroupList, entity,true);
                    groupTree.add(jsonObject);
                }
            }
        }
        return groupTree;
    }

    /**
     * 封装父分组的JSON
     * @param allGroupList 所有分组集合
     * @param entity
     * @return
     */
    public JSONObject formatGroupJSONObject(List<PublicGroupSeniorEntity> allGroupList,PublicGroupSeniorEntity entity,boolean isHaveChild){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("label",entity.getName());
        jsonObject.put("level",entity.getLevel());
        jsonObject.put("sort",entity.getSort());
        if (isHaveChild) {
            jsonObject.put("id",entity.getId());
            jsonObject.put("value",entity.getId());
            jsonObject.put("groupType",entity.getGroupType());
            jsonObject.put("parentId",entity.getParentId());
            jsonObject.put("children",getSubGroupTree(allGroupList,entity.getId()));
        }else {
            jsonObject.put("id",entity.getId());
            jsonObject.put("value",entity.getId());
            jsonObject.put("groupType",entity.getGroupType());
            jsonObject.put("parentId",entity.getId());
        }
        return jsonObject;
    }

    /**
     * 递归获取子分组树
     * @param allGroupList  所有分组集合
     * @param groupId
     * @return
     */
    public JSONArray getSubGroupTree(List<PublicGroupSeniorEntity> allGroupList,Long groupId){
        JSONArray subGroupList = new JSONArray();
        List<PublicGroupSeniorEntity> collect = allGroupList.stream().filter(entity -> Objects.equals(entity.getParentId(), groupId)).collect(Collectors.toList());
        for (PublicGroupSeniorEntity entity : collect ){
            JSONObject jsonObject = formatGroupJSONObject(null,entity,false);
            subGroupList.add(jsonObject);
        }
        allGroupList.remove(collect);
        if (CollectionsUtil.isEmpty(subGroupList)){
            return null;
        }
        for (Object object : subGroupList){
            JSONObject jsonObject = (JSONObject) object;
            jsonObject.put("children", getSubGroupTree(allGroupList, jsonObject.getLong("parentId")));
        }
        return subGroupList;
    }


    @Override
    public Integer updateBatchStatus(ChangeRuleStatusDTO statusDTO) throws XbbException {
        String corpid = statusDTO.getCorpid();
        try {
            List<PublicGroupSeniorEntity> entityList = getByFormId(statusDTO.getFormId(), corpid,BasicConstant.ZERO);
            Integer update = 0;
            List<PublicGroupSeniorEntity> collect =
                    entityList.stream().filter(item -> Objects.equals(item.getGroupType(), SeniorPublicGroupTypeEnum.NO_PUBLIC_GROUP.getType())).collect(Collectors.toList());
            if (CollectionsUtil.isEmpty(collect)){
                //如果是第一次进来新建模板，初始化一条无分组
                PublicGroupSeniorEntity entity = initNoPublicGroupEntity(corpid,statusDTO.getBusinessType(),statusDTO.getUserId(), statusDTO.getFormId());
                if(CollectionsUtil.isNotEmpty(entityList)){
                    entityList.forEach(item -> item.setStatus(statusDTO.getStatus()));
                    updateBatch(entityList, corpid);
                }
                return insert(entity);
            }else {
                entityList.forEach(item -> item.setStatus(statusDTO.getStatus()));
                update = updateBatch(entityList, corpid);
            }
            return update;
        } catch (Exception e) {
            LOG.error("publicGroupSeniorModel.updateBatchStatus状态启用失败",e);
            throw e;
        }
    }

    @Override
     public PublicGroupSeniorEntity initNoPublicGroup(String corpid,Integer businessType, String userId,Long formId) throws XbbException {
        return  initNoPublicGroupEntity(corpid,businessType,userId,formId);
    }

    /**
     * 高级模式下 第一次启用，初始化无分组
     * @param corpid
     * @param businessType
     * @param userId
     * @param formId
     */

    private PublicGroupSeniorEntity initNoPublicGroupEntity(String corpid,Integer businessType, String userId,Long formId){
        PublicGroupSeniorEntity entity = new PublicGroupSeniorEntity();
        entity.setCorpid(corpid);
        entity.setLevel(BasicConstant.ONE);
        entity.setParentId(BasicConstant.ZERO_LONG);
        if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
            entity.setName(SeniorFixedGroupEnum.NO_GROUP_CUSTOMER.getLabel());
        }else if (Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())){
            entity.setName(SeniorFixedGroupEnum.NO_GROUP_CLUE.getLabel());
        }
        entity.setSort(BasicConstant.ZERO);
        entity.setFormId(formId);
        entity.setJsonData(new JSONArray());
        entity.setScopeRule(new JSONArray());
        entity.setBusinessType(businessType);
        entity.setAdminScopeRule(new JSONArray());
        entity.setCreatorId(userId);
        entity.setModifierId(userId);
        entity.setStatus(BasicConstant.ONE);
        entity.setGroupType(SeniorPublicGroupTypeEnum.NO_PUBLIC_GROUP.getType());
        return entity;
    }

    @Override
    public Integer deleteByBusinessType(String corpid, Integer businessType) throws XbbException {
        return publicGroupSeniorDao.deleteByBusinessType(corpid, businessType);
    }

    @Override
    public List<PublicGroupSeniorEntity> filterGroupSeniorByUser(List<PublicGroupSeniorEntity> list, UserEntity user) {
        List<PublicGroupSeniorEntity> resultList = new ArrayList<>();
        // 角色数据
        List<Integer> roleIds = user.roleIdsToList();
        // 部门列表
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", user.getCorpid());
        param.put("del", DelEnum.NORMAL.getDel());
        List<DepartmentEntity> allDepartmentList = departmentModel.findEntitys(param);
        // 获得用户所属部门id列表
        List<Long> belongDepList = userModel.getUserBelongDeptIdList(user, false);

        for (PublicGroupSeniorEntity entity : list) {
            JSONArray scopeRule = entity.getScopeRule();
            JSONArray adminScopeRule = entity.getAdminScopeRule();
            List<OptionalRangeEntity> scopeRuleData;
            List<OptionalRangeEntity> adminScopeRuleData;
            try {
                scopeRuleData = scopeRule.toJavaList(OptionalRangeEntity.class);
                adminScopeRuleData = adminScopeRule.toJavaList(OptionalRangeEntity.class);
            } catch (JSONException e) {
                scopeRuleData = new ArrayList<>();
                adminScopeRuleData = new ArrayList<>();
            }
            // 未设置查看权限(梦娜说:未设置管理员和成员代表不能看和管理)
            if (scopeRuleData.size() <= 0 && adminScopeRuleData.size() <= 0) {
                //resultList.add(entity);
                continue;
            }

            List<Long> depIdArray = new ArrayList<>();
            List<Integer> roleIdArray = new ArrayList<>();
            List<String> userIdArray = new ArrayList<>();

            for (OptionalRangeEntity rangeEntity : scopeRuleData) {
                String property = rangeEntity.getProperty();
                String id = rangeEntity.getId();

                if (OptionalRangeEnum.DEPT.getValue().equals(property)) {
                    depIdArray.add(Long.parseLong(id));
                } else if (OptionalRangeEnum.ROLE.getValue().equals(property)) {
                    roleIdArray.add(Integer.parseInt(id));
                } else if (OptionalRangeEnum.USER.getValue().equals(property)) {
                    userIdArray.add(id);
                }
            }

            //有管理员权限也可以查看该分组
            for (OptionalRangeEntity rangeEntity : adminScopeRuleData) {
                String property = rangeEntity.getProperty();
                String id = rangeEntity.getId();

                if (OptionalRangeEnum.DEPT.getValue().equals(property)) {
                    depIdArray.add(Long.parseLong(id));
                } else if (OptionalRangeEnum.ROLE.getValue().equals(property)) {
                    roleIdArray.add(Integer.parseInt(id));
                } else if (OptionalRangeEnum.USER.getValue().equals(property)) {
                    userIdArray.add(id);
                }
            }

            // 未设置查看权限
            if (depIdArray.isEmpty() && roleIdArray.isEmpty() && userIdArray.isEmpty()) {
                resultList.add(entity);
                continue;
            }

            // 角色是否有交集
            roleIdArray.retainAll(roleIds);
            if (!roleIdArray.isEmpty()) {
                resultList.add(entity);
                continue;
            }

            // 全公司
            if (depIdArray.contains(1L)) {
                resultList.add(entity);
                continue;
            }

            // 获取有权限查看模板的部门以及子部门
            Set<Long> depIncludeSubSet = new LinkedHashSet<>();
            for (Long depId : depIdArray) {
                Set<Long> subDepIdList = UserUtil.getSubDepIdList(depId, allDepartmentList);
                depIncludeSubSet.addAll(subDepIdList);
            }
            depIncludeSubSet.retainAll(belongDepList);
            if (!depIncludeSubSet.isEmpty()) {
                resultList.add(entity);
                continue;
            }

            // 自定义人员匹配
            if (userIdArray.contains(user.getUserId())) {
                resultList.add(entity);
            }

        }
        return resultList;
    }

    /**
     * 返回 Map形式
     *
     * @author lijiangren
     * @date 2022-04-20 14 53
     */
    @Override
    public Map<Long, PublicGroupSeniorEntity> getPublicGroupMap(Long formId, String corpid) {
        Map<Long, PublicGroupSeniorEntity> publicGroupMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<PublicGroupSeniorEntity> seniorEntityList = publicGroupSeniorDao.getByFormId(formId, corpid, BasicConstant.ZERO);
        if (CollectionUtils.isEmpty(seniorEntityList)) {
            return publicGroupMap;
        }
        Map<Long, PublicGroupSeniorEntity> publicGroupSeniorMap = seniorEntityList.stream().
                collect(Collectors.toMap(PublicGroupSeniorEntity::getId, publicGroupSeniorEntity -> publicGroupSeniorEntity));
        return publicGroupSeniorMap;
    }
}
